<!DOCTYPE html>
<html>

<head>
  <title>JS进阶处理之专题汇总</title>
  <meta charset='utf-8'>
  <link href='https://cdn.maxiang.io/res-min/themes/marxico.css' rel='stylesheet'>
  <style>
    .note-content {
      font-family: "Helvetica Neue", Arial, "Hiragino Sans GB", STHeiti, "Microsoft YaHei", "WenQuanYi Micro Hei", SimSun, Song, sans-serif;
    }

    .toc ul {
      padding-left: 0;
    }

    #preview-contents {
      margin-top: -20px;
      width: 1000px;
    }
  </style>
</head>

<body>
  <div id='preview-contents' class='note-content'>
    <h4>专题：JS中THIS的五种情况梳理</h4>
    <ul>
      <li>
        <p>事件绑定</p>
      </li>
      <li>
        <p>函数执行（包括自执行函数 &amp; 回调函数）</p>
      </li>
      <li>
        <p>new构造函数</p>
      </li>
      <li>
        <p>箭头函数</p>
      </li>
      <li>
        <p>call/apply/bind</p>
      </li>
    </ul>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">~ <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">const</span> createRandom = <span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> ran = <span class="hljs-built_in">Math</span>.random() * <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> ran.toString(<span class="hljs-number">16</span>).replace(<span class="hljs-string">'.'</span>, <span class="hljs-string">''</span>);
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* 内置CALL实现原理 */</span>
</div><div class="hljs-line">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">change</span>(<span class="hljs-params">context, ...params</span>) </span>{
</div><div class="hljs-line">        context == <span class="hljs-literal">null</span> ? context = <span class="hljs-built_in">window</span> : <span class="hljs-literal">null</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (!<span class="hljs-regexp">/^(object|function)$/</span>.test(<span class="hljs-keyword">typeof</span> context)) context = <span class="hljs-built_in">Object</span>(context);
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> self = <span class="hljs-keyword">this</span>,
</div><div class="hljs-line">            key = <span class="hljs-built_in">Symbol</span>(<span class="hljs-string">'KEY'</span>),
</div><div class="hljs-line">            result;
</div><div class="hljs-line">        context[key] = self;
</div><div class="hljs-line">        result = context[key](...params);
</div><div class="hljs-line">        <span class="hljs-keyword">delete</span> context[key];
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> result;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">/* 内置BIND的实现原理 */</span>
</div><div class="hljs-line">    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">bind</span>(<span class="hljs-params">context, ...params</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> self = <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">proxy</span>(<span class="hljs-params">...args</span>) </span>{
</div><div class="hljs-line">            params = params.concat(args);
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> self.call(context, ...params);
</div><div class="hljs-line">        };
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-built_in">Function</span>.prototype.bind = bind;
</div><div class="hljs-line">    <span class="hljs-built_in">Function</span>.prototype.change = change;
</div><div class="hljs-line">}();
</div></code></pre>
    <p><strong>练习题</strong></p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">let</span> obj = {
</div><div class="hljs-line">    <span class="hljs-attr">fn</span>: (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">            <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>);
</div><div class="hljs-line">        }
</div><div class="hljs-line">    })()
</div><div class="hljs-line">};
</div><div class="hljs-line">obj.fn();
</div><div class="hljs-line"><span class="hljs-keyword">let</span> fn = obj.fn;
</div><div class="hljs-line">fn();
</div></code></pre>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">var</span> fullName = <span class="hljs-string">'language'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">var</span> obj = {
</div><div class="hljs-line">    <span class="hljs-attr">fullName</span>: <span class="hljs-string">'javascript'</span>,
</div><div class="hljs-line">    <span class="hljs-attr">prop</span>: {
</div><div class="hljs-line">        <span class="hljs-attr">getFullName</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.fullName;
</div><div class="hljs-line">        }
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div><div class="hljs-line"><span class="hljs-built_in">console</span>.log(obj.prop.getFullName());
</div><div class="hljs-line"><span class="hljs-keyword">var</span> test = obj.prop.getFullName;
</div><div class="hljs-line"><span class="hljs-built_in">console</span>.log(test());
</div></code></pre>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">var</span> name = <span class="hljs-string">'window'</span>;
</div><div class="hljs-line"><span class="hljs-keyword">var</span> Tom = {
</div><div class="hljs-line">    <span class="hljs-attr">name</span>: <span class="hljs-string">"Tom"</span>,
</div><div class="hljs-line">    <span class="hljs-attr">show</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(<span class="hljs-keyword">this</span>.name);
</div><div class="hljs-line">    },
</div><div class="hljs-line">    <span class="hljs-attr">wait</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> fun = <span class="hljs-keyword">this</span>.show;
</div><div class="hljs-line">        fun();
</div><div class="hljs-line">    }
</div><div class="hljs-line">};
</div><div class="hljs-line">Tom.wait();
</div></code></pre>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-built_in">window</span>.val = <span class="hljs-number">1</span>;
</div><div class="hljs-line"><span class="hljs-keyword">var</span> json = {
</div><div class="hljs-line">    <span class="hljs-attr">val</span>: <span class="hljs-number">10</span>,
</div><div class="hljs-line">    <span class="hljs-attr">dbl</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">this</span>.val *= <span class="hljs-number">2</span>;
</div><div class="hljs-line">    }
</div><div class="hljs-line">}
</div><div class="hljs-line">json.dbl();
</div><div class="hljs-line"><span class="hljs-keyword">var</span> dbl = json.dbl;
</div><div class="hljs-line">dbl();
</div><div class="hljs-line">json.dbl.call(<span class="hljs-built_in">window</span>);
</div><div class="hljs-line">alert(<span class="hljs-built_in">window</span>.val + json.val);
</div></code></pre>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> val = <span class="hljs-number">1</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> json = {
</div><div class="hljs-line">        <span class="hljs-attr">val</span>: <span class="hljs-number">10</span>,
</div><div class="hljs-line">        <span class="hljs-attr">dbl</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">            val *= <span class="hljs-number">2</span>;
</div><div class="hljs-line">        }
</div><div class="hljs-line">    };
</div><div class="hljs-line">    json.dbl();
</div><div class="hljs-line">    alert(json.val + val);
</div><div class="hljs-line">})();
</div></code></pre>


    <hr>

    <h4>专题：JQ源码阅读</h4>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line"><span class="hljs-meta">    "use strict"</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> arr = [];
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> slice = arr.slice;
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> push = arr.push;
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> indexOf = arr.indexOf;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// =======</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> version = <span class="hljs-string">"3.5.1"</span>,
</div><div class="hljs-line">        jQuery = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">jQuery</span>(<span class="hljs-params">selector, context</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> jQuery.fn.init(selector, context);
</div><div class="hljs-line">        };
</div><div class="hljs-line">    jQuery.fn = jQuery.prototype = {
</div><div class="hljs-line">        <span class="hljs-attr">constructor</span>: jQuery,
</div><div class="hljs-line">        <span class="hljs-attr">jquery</span>: version,
</div><div class="hljs-line">        <span class="hljs-attr">length</span>: <span class="hljs-number">0</span>,
</div><div class="hljs-line">        <span class="hljs-attr">push</span>: push,
</div><div class="hljs-line">        <span class="hljs-attr">sort</span>: arr.sort,
</div><div class="hljs-line">        <span class="hljs-attr">splice</span>: arr.splice,
</div><div class="hljs-line">        <span class="hljs-attr">get</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">num</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (num == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> slice.call(<span class="hljs-keyword">this</span>);
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> num &lt; <span class="hljs-number">0</span> ? <span class="hljs-keyword">this</span>[num + <span class="hljs-keyword">this</span>.length] : <span class="hljs-keyword">this</span>[num];
</div><div class="hljs-line">        },
</div><div class="hljs-line">        <span class="hljs-attr">eq</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">i</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">var</span> len = <span class="hljs-keyword">this</span>.length,
</div><div class="hljs-line">                j = +i + (i &lt; <span class="hljs-number">0</span> ? len : <span class="hljs-number">0</span>);
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.pushStack(j &gt;= <span class="hljs-number">0</span> &amp;&amp; j &lt; len ? [<span class="hljs-keyword">this</span>[j]] : []);
</div><div class="hljs-line">        },
</div><div class="hljs-line">        <span class="hljs-attr">pushStack</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">elems</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">var</span> ret = jQuery.merge(<span class="hljs-keyword">this</span>.constructor(), elems);
</div><div class="hljs-line">            ret.prevObject = <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> ret;
</div><div class="hljs-line">        },
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    jQuery.merge = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">merge</span>(<span class="hljs-params">first, second</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> len = +second.length,
</div><div class="hljs-line">            j = <span class="hljs-number">0</span>,
</div><div class="hljs-line">            i = first.length;
</div><div class="hljs-line">        <span class="hljs-keyword">for</span> (; j &lt; len; j++) {
</div><div class="hljs-line">            first[i++] = second[j];
</div><div class="hljs-line">        }
</div><div class="hljs-line">        first.length = i;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> first;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// =======</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> rootjQuery = jQuery(<span class="hljs-built_in">document</span>),
</div><div class="hljs-line">        rquickExpr = <span class="hljs-regexp">/^(?:\s*(&lt;[\w\W]+&gt;)[^&gt;]*|#([\w-]+))$/</span>,
</div><div class="hljs-line">        init = jQuery.fn.init = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">init</span>(<span class="hljs-params">selector, context, root</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">var</span> match, elem;
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (!selector) <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">            root = root || rootjQuery;
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> selector === <span class="hljs-string">"string"</span>) {
</div><div class="hljs-line">                <span class="hljs-keyword">if</span> (selector[<span class="hljs-number">0</span>] === <span class="hljs-string">"&lt;"</span> &amp;&amp;
</div><div class="hljs-line">                    selector[selector.length - <span class="hljs-number">1</span>] === <span class="hljs-string">"&gt;"</span> &amp;&amp;
</div><div class="hljs-line">                    selector.length &gt;= <span class="hljs-number">3</span>) {
</div><div class="hljs-line">                    match = [<span class="hljs-literal">null</span>, selector, <span class="hljs-literal">null</span>];
</div><div class="hljs-line">                } <span class="hljs-keyword">else</span> {
</div><div class="hljs-line">                    match = rquickExpr.exec(selector);
</div><div class="hljs-line">                }
</div><div class="hljs-line">                <span class="hljs-keyword">if</span> (match &amp;&amp; (match[<span class="hljs-number">1</span>] || !context)) {
</div><div class="hljs-line">                    <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>]) {
</div><div class="hljs-line">                        context = context <span class="hljs-keyword">instanceof</span> jQuery ? context[<span class="hljs-number">0</span>] : context;
</div><div class="hljs-line">                        jQuery.merge(<span class="hljs-keyword">this</span>, jQuery.parseHTML(
</div><div class="hljs-line">                            match[<span class="hljs-number">1</span>],
</div><div class="hljs-line">                            context &amp;&amp; context.nodeType ? context.ownerDocument || context : <span class="hljs-built_in">document</span>,
</div><div class="hljs-line">                            <span class="hljs-literal">true</span>
</div><div class="hljs-line">                        ));
</div><div class="hljs-line">                        <span class="hljs-keyword">if</span> (rsingleTag.test(match[<span class="hljs-number">1</span>]) &amp;&amp; jQuery.isPlainObject(context)) {
</div><div class="hljs-line">                            <span class="hljs-keyword">for</span> (match <span class="hljs-keyword">in</span> context) {
</div><div class="hljs-line">                                <span class="hljs-keyword">if</span> (isFunction(<span class="hljs-keyword">this</span>[match])) {
</div><div class="hljs-line">                                    <span class="hljs-keyword">this</span>[match](context[match]);
</div><div class="hljs-line">                                } <span class="hljs-keyword">else</span> {
</div><div class="hljs-line">                                    <span class="hljs-keyword">this</span>.attr(match, context[match]);
</div><div class="hljs-line">                                }
</div><div class="hljs-line">                            }
</div><div class="hljs-line">                        }
</div><div class="hljs-line">                        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">                    } <span class="hljs-keyword">else</span> {
</div><div class="hljs-line">                        elem = <span class="hljs-built_in">document</span>.getElementById(match[<span class="hljs-number">2</span>]);
</div><div class="hljs-line">                        <span class="hljs-keyword">if</span> (elem) {
</div><div class="hljs-line">                            <span class="hljs-keyword">this</span>[<span class="hljs-number">0</span>] = elem;
</div><div class="hljs-line">                            <span class="hljs-keyword">this</span>.length = <span class="hljs-number">1</span>;
</div><div class="hljs-line">                        }
</div><div class="hljs-line">                        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">                    }
</div><div class="hljs-line">                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!context || context.jquery) {
</div><div class="hljs-line">                    <span class="hljs-keyword">return</span> (context || root).find(selector);
</div><div class="hljs-line">                } <span class="hljs-keyword">else</span> {
</div><div class="hljs-line">                    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.constructor(context).find(selector);
</div><div class="hljs-line">                }
</div><div class="hljs-line">            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (selector.nodeType) {
</div><div class="hljs-line">                <span class="hljs-keyword">this</span>[<span class="hljs-number">0</span>] = selector;
</div><div class="hljs-line">                <span class="hljs-keyword">this</span>.length = <span class="hljs-number">1</span>;
</div><div class="hljs-line">                <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (isFunction(selector)) {
</div><div class="hljs-line">                <span class="hljs-keyword">return</span> root.ready !== <span class="hljs-literal">undefined</span> ?
</div><div class="hljs-line">                    root.ready(selector) :
</div><div class="hljs-line">                    selector(jQuery);
</div><div class="hljs-line">            }
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> jQuery.makeArray(selector, <span class="hljs-keyword">this</span>);
</div><div class="hljs-line">        };
</div><div class="hljs-line">    init.prototype = jQuery.fn;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// =======</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> readyList = jQuery.Deferred();
</div><div class="hljs-line">    jQuery.fn.ready = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">fn</span>) </span>{
</div><div class="hljs-line">        readyList
</div><div class="hljs-line">            .then(fn)
</div><div class="hljs-line">            .catch(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error</span>) </span>{
</div><div class="hljs-line">                jQuery.readyException(error);
</div><div class="hljs-line">            });
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// =======</span>
</div><div class="hljs-line">    jQuery.makeArray = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">makeArray</span>(<span class="hljs-params">arr, results</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> ret = results || [];
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (arr != <span class="hljs-literal">null</span>) {
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (isArrayLike(<span class="hljs-built_in">Object</span>(arr))) {
</div><div class="hljs-line">                jQuery.merge(ret,
</div><div class="hljs-line">                    <span class="hljs-keyword">typeof</span> arr === <span class="hljs-string">"string"</span> ? [arr] : arr
</div><div class="hljs-line">                );
</div><div class="hljs-line">            } <span class="hljs-keyword">else</span> {
</div><div class="hljs-line">                push.call(ret, arr);
</div><div class="hljs-line">            }
</div><div class="hljs-line">        }
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> ret;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// =======</span>
</div><div class="hljs-line">    <span class="hljs-built_in">window</span>.jQuery = <span class="hljs-built_in">window</span>.$ = jQuery;
</div><div class="hljs-line">})();
</div></code></pre>

    <hr>

    <h4>专题：JS中数据类型检测汇总</h4>
    <ul>
      <li>
        <p>typeof</p>

        <ul>
          <li>
            <p>底层原理</p>
          </li>
          <li>
            <p>扩展 0.1+0.2!==0.3</p>
          </li>
        </ul>
      </li>
      <li>
        <p>instanceof </p>

        <ul>
          <li>
            <p>底层原理及相关问题</p>
          </li>
          <li>
            <p>Symbol.hasInstance</p>
          </li>
          <li>
            <p>重写instanceof</p>
          </li>
        </ul>
      </li>
      <li>
        <p>constructor</p>
      </li>
      <li>
        <p>Object.prototype.toString.call(value)</p>

        <ul>
          <li>
            <p>value[Symbol.toStringTag]</p>
          </li>
        </ul>
      </li>
    </ul>
    <p><strong>重写instanceof</strong></p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">instance_of</span>(<span class="hljs-params">obj, Ctor</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-comment">// 数据格式准确性校验</span>
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (Ctor == <span class="hljs-literal">null</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">"Right-hand side of 'instanceof' is not an object"</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (!Ctor.prototype) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">"Function has non-object prototype 'undefined' in instanceof check"</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> Ctor !== <span class="hljs-string">"function"</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">"Right-hand side of 'instanceof' is not callable"</span>);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 原始类型直接忽略</span>
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (obj == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (!<span class="hljs-regexp">/^(object|function)$/</span>.test(<span class="hljs-keyword">typeof</span> obj)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 先检测是否有 Symbol.hasInstance 这个属性</span>
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> Ctor[<span class="hljs-built_in">Symbol</span>.hasInstance] === <span class="hljs-string">"function"</span>) <span class="hljs-keyword">return</span> Ctor[<span class="hljs-built_in">Symbol</span>.hasInstance](obj);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 最后才会按照原型链进行处理</span>
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> prototype = <span class="hljs-built_in">Object</span>.getPrototypeOf(obj);
</div><div class="hljs-line">    <span class="hljs-keyword">while</span> (prototype) {
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (prototype === Ctor.prototype) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
</div><div class="hljs-line">        prototype = <span class="hljs-built_in">Object</span>.getPrototypeOf(prototype);
</div><div class="hljs-line">    }
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">}
</div></code></pre>
    <p><strong>JQ中数据类型检测方法</strong></p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line"><span class="hljs-meta">    "use strict"</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> getProto = <span class="hljs-built_in">Object</span>.getPrototypeOf,
</div><div class="hljs-line">        class2type = {},
</div><div class="hljs-line">        toString = class2type.toString,
</div><div class="hljs-line">        hasOwn = class2type.hasOwnProperty,
</div><div class="hljs-line">        fnToString = hasOwn.toString,
</div><div class="hljs-line">        ObjectFunctionString = fnToString.call(<span class="hljs-built_in">Object</span>);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 专门进行数据类型检测的办法 </span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> toType = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toType</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (obj == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> obj + <span class="hljs-string">""</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> obj !== <span class="hljs-string">"object"</span> &amp;&amp; <span class="hljs-keyword">typeof</span> obj !== <span class="hljs-string">"function"</span>) <span class="hljs-keyword">return</span> <span class="hljs-keyword">typeof</span> obj;
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> reg = <span class="hljs-regexp">/^\[object ([0-9A-Za-z]+)\]$/</span>,
</div><div class="hljs-line">            value = reg.exec(toString.call(obj))[<span class="hljs-number">1</span>] || <span class="hljs-string">"object"</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> value.toLowerCase();
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 检测是否为一个函数</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> isFunction = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isFunction</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="hljs-keyword">typeof</span> obj === <span class="hljs-string">"function"</span> &amp;&amp; <span class="hljs-keyword">typeof</span> obj.nodeType !== <span class="hljs-string">"number"</span>;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 检测是否为一个window对象</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> isWindow = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isWindow</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> obj != <span class="hljs-literal">null</span> &amp;&amp; obj === obj.window;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 检测是否为数组或者类数组</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> isArrayLike = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isArrayLike</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> length = !!obj &amp;&amp; <span class="hljs-string">"length"</span> <span class="hljs-keyword">in</span> obj &amp;&amp; obj.length,
</div><div class="hljs-line">            type = toType(obj);
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (isFunction(obj) || isWindow(obj)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> type === <span class="hljs-string">"array"</span> || length === <span class="hljs-number">0</span> ||
</div><div class="hljs-line">            <span class="hljs-keyword">typeof</span> length === <span class="hljs-string">"number"</span> &amp;&amp; length &gt; <span class="hljs-number">0</span> &amp;&amp; (length - <span class="hljs-number">1</span>) <span class="hljs-keyword">in</span> obj;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 检测是否为纯粹的对象</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> isPlainObject = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isPlainObject</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> proto, Ctor;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (!obj || toType(obj) !== <span class="hljs-string">"object"</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">        proto = getProto(obj);
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (!proto) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
</div><div class="hljs-line">        Ctor = hasOwn.call(proto, <span class="hljs-string">"constructor"</span>) &amp;&amp; proto.constructor;
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> <span class="hljs-keyword">typeof</span> Ctor === <span class="hljs-string">"function"</span> &amp;&amp; fnToString.call(Ctor) === ObjectFunctionString;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 检测是否为空对象</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> isEmptyObject = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isEmptyObject</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (obj == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> keys = <span class="hljs-built_in">Object</span>.keys(obj);
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">Symbol</span> !== <span class="hljs-string">"undefined"</span>) {
</div><div class="hljs-line">            keys = keys.concat(<span class="hljs-built_in">Object</span>.getOwnPropertySymbols(obj));
</div><div class="hljs-line">        }
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> keys.length === <span class="hljs-number">0</span>;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 检测是否为数字</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> isNumeric = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">isNumeric</span>(<span class="hljs-params">obj</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> type = toType(obj);
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> (type === <span class="hljs-string">"number"</span> || type === <span class="hljs-string">"string"</span>) &amp;&amp; !<span class="hljs-built_in">isNaN</span>(+obj);
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    ......
</div><div class="hljs-line">})();
</div></code></pre>

    <hr>

    <h4>专题：数组和对象的深浅克隆 &amp; 深浅合并</h4>
    <blockquote>
      <p>简单说下深拷贝&amp;浅拷贝，哪些对象不能用JSON深克隆？ </p>
    </blockquote>
    <ul>
      <li>
        <p>堆栈内存</p>
      </li>
      <li>
        <p>深拷贝 VS 浅拷贝</p>
      </li>
      <li>
        <p>哪些对象不能用JSON深克隆？</p>

        <ul>
          <li>
            <p>不允许出现套娃操作</p>
          </li>
          <li>
            <p>属性值不能是BigInt</p>
          </li>
          <li>
            <p>丢失一些内容：只要属性值是 symbol/undefined/function 这些类型的</p>
          </li>
          <li>
            <p>还有信息不准确的，例如：正则-&gt;空对象 Error对象-&gt;空对象 日期对象-&gt;字符串 …</p>
          </li>
        </ul>
      </li>
    </ul>
    <blockquote>
      <p>数组对象的浅合并「浅比较」 &amp; 深合并「深比较」</p>
    </blockquote>
    <ul>
      <li>
        <p>Object.assign</p>
      </li>
    </ul>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line">(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line"><span class="hljs-meta">    "use strict"</span>;
</div><div class="hljs-line">    <span class="hljs-comment">// 实现数组和对象深/浅合并</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> merge = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">merge</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> options,
</div><div class="hljs-line">            target = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>] || {},
</div><div class="hljs-line">            i = <span class="hljs-number">1</span>,
</div><div class="hljs-line">            length = <span class="hljs-built_in">arguments</span>.length,
</div><div class="hljs-line">            treated = <span class="hljs-built_in">arguments</span>[length - <span class="hljs-number">1</span>],
</div><div class="hljs-line">            deep = <span class="hljs-literal">false</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> target === <span class="hljs-string">"boolean"</span>) {
</div><div class="hljs-line">            deep = target;
</div><div class="hljs-line">            target = <span class="hljs-built_in">arguments</span>[i] || {};
</div><div class="hljs-line">            i++;
</div><div class="hljs-line">        }
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Array</span>.isArray(treated) &amp;&amp; treated.treated) {
</div><div class="hljs-line">            <span class="hljs-comment">// 传递了记录已经处理过的内容的集合</span>
</div><div class="hljs-line">            <span class="hljs-comment">// 后期循环的时候少循环处理一项</span>
</div><div class="hljs-line">            length--;
</div><div class="hljs-line">        } <span class="hljs-keyword">else</span> {
</div><div class="hljs-line">            <span class="hljs-comment">// 没传递，最后传递的这个值，不是用来存储处理过的内容，而是进行合并比较的</span>
</div><div class="hljs-line">            treated = [];
</div><div class="hljs-line">            treated.treated = <span class="hljs-literal">true</span>;
</div><div class="hljs-line">        }
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> target !== <span class="hljs-string">"object"</span> &amp;&amp; !isFunction(target)) target = {};
</div><div class="hljs-line">        <span class="hljs-keyword">for</span> (; i &lt; length; i++) {
</div><div class="hljs-line">            options = <span class="hljs-built_in">arguments</span>[i];
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (options == <span class="hljs-literal">null</span>) <span class="hljs-keyword">continue</span>;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">            <span class="hljs-comment">// 放置死递归处理的操作</span>
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (treated.indexOf(options) &gt; <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> options;
</div><div class="hljs-line">            treated.push(options);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">            each(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">copy, name</span>) </span>{
</div><div class="hljs-line">                <span class="hljs-keyword">var</span> copyIsArray = <span class="hljs-built_in">Array</span>.isArray(copy),
</div><div class="hljs-line">                    copyIsObject = isPlainObject(copy),
</div><div class="hljs-line">                    src = target[name],
</div><div class="hljs-line">                    clone = src;
</div><div class="hljs-line">                <span class="hljs-keyword">if</span> (deep &amp;&amp; copy &amp;&amp; (copyIsArray || copyIsObject)) {
</div><div class="hljs-line">                    <span class="hljs-keyword">if</span> (copyIsArray &amp;&amp; !<span class="hljs-built_in">Array</span>.isArray(src)) clone = [];
</div><div class="hljs-line">                    <span class="hljs-keyword">if</span> (copyIsObject &amp;&amp; !isPlainObject(src)) clone = {};
</div><div class="hljs-line">                    target[name] = merge(deep, clone, copy, treated);
</div><div class="hljs-line">                } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (copy !== <span class="hljs-literal">undefined</span>) {
</div><div class="hljs-line">                    target[name] = copy;
</div><div class="hljs-line">                }
</div><div class="hljs-line">            });
</div><div class="hljs-line">        }
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> target;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    <span class="hljs-comment">// 实现数组和对象深/浅拷贝</span>
</div><div class="hljs-line">    <span class="hljs-keyword">var</span> clone = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clone</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">var</span> target = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>],
</div><div class="hljs-line">            deep = <span class="hljs-literal">false</span>,
</div><div class="hljs-line">            type,
</div><div class="hljs-line">            isArray,
</div><div class="hljs-line">            isObject,
</div><div class="hljs-line">            result,
</div><div class="hljs-line">            Ctor,
</div><div class="hljs-line">            treated = <span class="hljs-built_in">arguments</span>[<span class="hljs-built_in">arguments</span>.length - <span class="hljs-number">1</span>];
</div><div class="hljs-line">        !<span class="hljs-built_in">Array</span>.isArray(treated) || !treated.treated ? (treated = [], treated.treated = <span class="hljs-literal">true</span>) : <span class="hljs-literal">null</span>;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> target === <span class="hljs-string">"boolean"</span>) {
</div><div class="hljs-line">            deep = target;
</div><div class="hljs-line">            target = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">1</span>];
</div><div class="hljs-line">        }
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-comment">// 防止死递归的处理</span>
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (treated.indexOf(target) &gt; <span class="hljs-number">-1</span>) <span class="hljs-keyword">return</span> target;
</div><div class="hljs-line">        treated.push(target);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-comment">// 校验类型</span>
</div><div class="hljs-line">        type = toType(target);
</div><div class="hljs-line">        isArray = <span class="hljs-built_in">Array</span>.isArray(target);
</div><div class="hljs-line">        isObject = isPlainObject(target);
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-comment">// 特殊值的拷贝</span>
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (target == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> target;
</div><div class="hljs-line">        Ctor = target.constructor;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-regexp">/^(regexp|date)$/i</span>.test(type)) <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Ctor(target);
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-regexp">/^(error)$/i</span>.test(type)) <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Ctor(target.message);
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (<span class="hljs-regexp">/^(function|generatorfunction)$/i</span>.test(type)) {
</div><div class="hljs-line">            <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">proxy</span>(<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">                <span class="hljs-keyword">var</span> args = <span class="hljs-built_in">Array</span>.from(<span class="hljs-built_in">arguments</span>);
</div><div class="hljs-line">                <span class="hljs-keyword">return</span> target.apply(<span class="hljs-keyword">this</span>, args);
</div><div class="hljs-line">            };
</div><div class="hljs-line">        }
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (!isArray &amp;&amp; !isObject) <span class="hljs-keyword">return</span> target;
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">        <span class="hljs-comment">// 如果是数组/对象，我们依次迭代赋值给新的数组/对象</span>
</div><div class="hljs-line">        result = <span class="hljs-keyword">new</span> Ctor();
</div><div class="hljs-line">        each(target, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">copy, name</span>) </span>{
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (deep) {
</div><div class="hljs-line">                <span class="hljs-comment">// 深拷贝</span>
</div><div class="hljs-line">                result[name] = clone(deep, copy, treated);
</div><div class="hljs-line">                <span class="hljs-keyword">return</span>;
</div><div class="hljs-line">            }
</div><div class="hljs-line">            <span class="hljs-comment">// 浅拷贝</span>
</div><div class="hljs-line">            result[name] = copy;
</div><div class="hljs-line">        });
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> result;
</div><div class="hljs-line">    };
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line">    ......
</div><div class="hljs-line">})();
</div></code></pre>

    <hr>

    <h4>专题：函数的防抖和节流处理</h4>
    <blockquote>
      <p>防抖 debounce：在用户频繁触发某个行为的时候，我们只识别一次即可「开始边界：第一次点击触发 结束边界：等到最后一次触发」 <br>
        节流 throttle：在频繁操作的时候，我们能降低触发的频率 <br>
        备注：频繁的频率自己来设定</p>
    </blockquote>
    <p>防抖的一种简单办法「具体的需求：频繁点击，只有当上一个请求成功，才能发送下一个请求」</p>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-keyword">let</span> isRun = <span class="hljs-literal">false</span>;
</div><div class="hljs-line">submit.onclick = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (isRun) <span class="hljs-keyword">return</span>;
</div><div class="hljs-line">    isRun = <span class="hljs-literal">true</span>;
</div><div class="hljs-line">    queryData(<span class="hljs-function"><span class="hljs-params">result</span> =&gt;</span> {
</div><div class="hljs-line">        <span class="hljs-built_in">console</span>.log(result);
</div><div class="hljs-line">        isRun = <span class="hljs-literal">false</span>;
</div><div class="hljs-line">    });
</div><div class="hljs-line">};
</div></code></pre>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">// 清除指定的定时器，并且让timer=null</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> clearTimer = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">clearTimer</span>(<span class="hljs-params">timer</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (timer) {
</div><div class="hljs-line">        clearTimeout(timer);
</div><div class="hljs-line">    }
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
</div><div class="hljs-line">};
</div><div class="hljs-line"><wbr>
</div><div class="hljs-line"><span class="hljs-comment">/*</span>
</div><div class="hljs-line"><span class="hljs-comment"> * debounce:函数防抖</span>
</div><div class="hljs-line"><span class="hljs-comment"> *  @params</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    func:自己最终要执行的任务</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    wait:多久操作一次算是频繁触发「默认值:500ms」</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    immediate:控制触发的边界 「默认值:false结束边界  true开始边界」</span>
</div><div class="hljs-line"><span class="hljs-comment"> *  @return</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    operate处理函数，处理函数会在频繁触发的时候，频繁执行；函数内部，控制我们想要操作的func只执行一次；</span>
</div><div class="hljs-line"><span class="hljs-comment"> */</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> debounce = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">debounce</span>(<span class="hljs-params">func, wait, immediate</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> func !== <span class="hljs-string">"function"</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">'func must be an function!'</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> wait === <span class="hljs-string">"boolean"</span>) immediate = wait;
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> wait !== <span class="hljs-string">"number"</span>) wait = <span class="hljs-number">500</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> immediate !== <span class="hljs-string">"boolean"</span>) immediate = <span class="hljs-literal">false</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> timer = <span class="hljs-literal">null</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">operate</span>(<span class="hljs-params">...params</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> now = !timer &amp;&amp; immediate,
</div><div class="hljs-line">            result;
</div><div class="hljs-line">        timer = clearTimer(timer);
</div><div class="hljs-line">        timer = setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">            timer = clearTimer(timer);
</div><div class="hljs-line">            <span class="hljs-comment">// 结束边界触发</span>
</div><div class="hljs-line">            <span class="hljs-keyword">if</span> (!immediate) func.call(<span class="hljs-keyword">this</span>, ...params);
</div><div class="hljs-line">        }, wait);
</div><div class="hljs-line">        <span class="hljs-comment">// 开始边界触发</span>
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (now) result = func.call(<span class="hljs-keyword">this</span>, ...params);
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> result;
</div><div class="hljs-line">    };
</div><div class="hljs-line">};
</div></code></pre>
    <pre class="prettyprint hljs-dark"><code class="language-javascript hljs"><div class="hljs-line"><span class="hljs-comment">/*</span>
</div><div class="hljs-line"><span class="hljs-comment"> * throttle:函数节流</span>
</div><div class="hljs-line"><span class="hljs-comment"> *  @params</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    func:自己最终要执行的任务</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    wait:触发的频率「默认值:500ms」</span>
</div><div class="hljs-line"><span class="hljs-comment"> *  @return</span>
</div><div class="hljs-line"><span class="hljs-comment"> *    operate处理函数</span>
</div><div class="hljs-line"><span class="hljs-comment"> */</span>
</div><div class="hljs-line"><span class="hljs-keyword">const</span> throttle = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">throttle</span>(<span class="hljs-params">func, wait</span>) </span>{
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> func !== <span class="hljs-string">"function"</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">'func must be an function!'</span>);
</div><div class="hljs-line">    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> wait !== <span class="hljs-string">"number"</span>) wait = <span class="hljs-number">500</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">let</span> timer = <span class="hljs-literal">null</span>,
</div><div class="hljs-line">        previous = <span class="hljs-number">0</span>;
</div><div class="hljs-line">    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">operate</span>(<span class="hljs-params">...params</span>) </span>{
</div><div class="hljs-line">        <span class="hljs-keyword">let</span> now = +<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
</div><div class="hljs-line">            remaining = wait - (now - previous),
</div><div class="hljs-line">            result;
</div><div class="hljs-line">        <span class="hljs-keyword">if</span> (remaining &lt;= <span class="hljs-number">0</span>) {
</div><div class="hljs-line">            <span class="hljs-comment">// 两次间隔时间超过500ms了,让方法立即执行</span>
</div><div class="hljs-line">            timer = clearTimer(timer);
</div><div class="hljs-line">            result = func.call(<span class="hljs-keyword">this</span>, ...params);
</div><div class="hljs-line">            previous = +<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
</div><div class="hljs-line">        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!timer) {
</div><div class="hljs-line">            <span class="hljs-comment">// 没设置过定时器等待，则我们设置一个去等待即可</span>
</div><div class="hljs-line">            timer = setTimeout(<span class="hljs-function"><span class="hljs-params">()</span> =&gt;</span> {
</div><div class="hljs-line">                timer = clearTimer(timer);
</div><div class="hljs-line">                func.call(<span class="hljs-keyword">this</span>, ...params);
</div><div class="hljs-line">                previous = +<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
</div><div class="hljs-line">            }, remaining);
</div><div class="hljs-line">        }
</div><div class="hljs-line">        <span class="hljs-keyword">return</span> result;
</div><div class="hljs-line">    };
</div><div class="hljs-line">};
</div></code></pre>

    <hr>

    <h4>专题：类的多种继承方案</h4>
    <ul>
      <li>
        <p>call继承</p>
      </li>
      <li>
        <p>原型继承</p>
      </li>
      <li>
        <p>寄生混合式继承</p>
      </li>
      <li>
        <p>ES6中的extend</p>
      </li>
    </ul>
  </div>
</body>

</html>